package alkaid.oss.local.controller;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import alkaid.oss.common.util.FileNameCounter;
import alkaid.oss.local.component.FileData;
import alkaid.oss.local.component.FileSystemStorageComponent;
import alkaid.oss.local.domain.FileMetadata;
import alkaid.oss.local.domain.FileMetadataRepository;
import alkaid.oss.local.domain.FileMetadataService;

/**
 * 文件接口
 * 
 * @author Lucky Yang
 * @since 0.0.1
 */
@RestController
@RequestMapping("/files")
public class FileController {
	@Autowired
	private FileSystemStorageComponent storage;
	@Autowired
	private FileMetadataService fileMetadataService;
	@Autowired
	private FileMetadataRepository fileMetadataRepository;

	@PostMapping("/upload")
	@ResponseStatus(HttpStatus.CREATED)
	public FileMetadataDto upload(@RequestParam("file") MultipartFile file) {
		FileMetadata entity = storage.store(file);
		return FileMetadataMapper.INST.toDto(entity);
	}

	@GetMapping("/download/{fileMetadataId}")
	public void download(@PathVariable Long fileMetadataId, final HttpServletResponse response)
			throws IOException {
		FileMetadata fmd = fileMetadataService.findById(fileMetadataId);

		// 文件数据
		final FileData fileData = storage.download(fmd);
		// 设置响应
		response.setContentType(fileData.contentType);
		response.setHeader("Content-Disposition",
				String.format("inline; filename=\"" + fileData.name + "\""));
		FileCopyUtils.copy(fileData.content.getInputStream(), response.getOutputStream());
	}

	@GetMapping(value = "/download-zip")
	public void downloads(@RequestParam(name = "fileMetadataIds") Set<Long> fileMetadataIds,
			HttpServletResponse response) throws IOException {
		byte[] buffer = new byte[2048];
		// 查询元数据
		List<FileMetadata> fmdList = fileMetadataRepository.findAllById(fileMetadataIds);
		try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
				ZipOutputStream zos = new ZipOutputStream(baos)) {
			FileNameCounter fileNameCounter = new FileNameCounter();

			for (FileMetadata fmd : fmdList) {
				FileData fileData = storage.download(fmd);
				// 避免重复的文件名
				ZipEntry zipEntry = new ZipEntry(fileNameCounter.convert(fileData.name));
				zos.putNextEntry(zipEntry);

				InputStream is = fileData.content.getInputStream();
				int bytesRead;
				while ((bytesRead = is.read(buffer)) != -1) {
					zos.write(buffer, 0, bytesRead);
				}

				zos.closeEntry();
			}
			response.setContentType("application/zip");
			response.addHeader("Pragma", "no-cache");
			response.addHeader("Expires", "0");
			final ServletOutputStream sos = response.getOutputStream();
			sos.write(baos.toByteArray());
			sos.flush();
		}
	}

	@DeleteMapping("/{fileMetadataId}")
	@ResponseStatus(HttpStatus.NO_CONTENT)
	public void remove(@PathVariable Long fileMetadataId) throws IOException {
		storage.remove(fileMetadataId);
	}
}
